package cn.edu.swu.toy;

import cn.edu.swu.core.BasicServlet;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload2.core.DiskFileItemFactory;
import org.apache.commons.fileupload2.core.FileItem;
import org.apache.commons.fileupload2.jakarta.servlet6.JakartaServletFileUpload;

import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.nio.charset.Charset;
import java.sql.*;
import java.text.ParseException;
import java.util.List;
import java.util.UUID;


/**
 * http://127.0.0.1:8090/toystore/toy
 * 显示 toy ：GET，  http://127.0.0.1:8090/toystore/toy/list
 * 添加 toy ：POST， http://127.0.0.1:8090/toystore/toy/add
 * 删除 toy ：GET，  http://127.0.0.1:8090/toystore/toy/delete?id=29
 * 修改 toy ：POST， http://127.0.0.1:8090/toystore/toy/update
 * 查询 toy ：GET，  http://127.0.0.1:8090/toystore/toy/search?key=编程

 http://localhost:8080/bookstore/book/css/bookstore.css
 http://localhost:8080/bookstore/css/bookstore.css
 */

@WebServlet(urlPatterns = "/toy/*")
public class ToyController extends BasicServlet {

    private ToyService toyService = null;

    // 上传文件存储目录
    private static final String UPLOAD_DIRECTORY = "upload";

    // 上传配置
    private static final int MEMORY_THRESHOLD   = 1024 * 1024 * 3;
    private static final int MAX_FILE_SIZE      = 1024 * 1024 * 40;
    private static final int MAX_REQUEST_SIZE   = 1024 * 1024 * 50;


    public void init(ServletConfig config) {
        ToyRepo repo = new ToyRepo();
        toyService = new ToyService();
        toyService.setRepo(repo);
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException {
        this.methodRoute(request, response);
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException {
        this.methodRoute(request, response);
    }

    private void methodRoute(HttpServletRequest request, HttpServletResponse response) throws ServletException {
        String uri = request.getRequestURI();
        String method = uri.substring(uri.lastIndexOf("/") + 1);

        try {
            if (method.equals("list")) {
                this.list(request, response);
            } else if (method.equals("add")) {
                this.add(request, response);
            } else if (method.equals("delete")) {
                this.delete(request, response);
            } else if (method.equals("edit")) {
                this.edit(request, response);
            } else if (method.equals("update")) {
                this.update(request, response);
            } else if (method.equals("search")) {
                this.search(request, response);
            }
        } catch (SQLException | IOException e) {
            throw new ServletException(e);
        }
    }

    public void list(HttpServletRequest request, HttpServletResponse response) throws ServletException{
        try {
            List<Toy> toys = this.toyService.getAll();
            try(Writer writer = response.getWriter()) {
                String table = this.wrapTable(toys);
                String page  = this.wrapPage(table);
                writer.write(page);
            }
        } catch (SQLException | IOException e) {
            throw new ServletException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    public void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, SQLException {
        this.save(request, response);
    }

    private void update(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, SQLException {
        this.save(request, response);
    }

    private void delete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, SQLException {
        int id = Integer.parseInt(request.getParameter("id"));
        this.toyService.deleteById(id);
        response.sendRedirect("./list");
    }

    private void edit(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, SQLException {
        int id = Integer.parseInt(request.getParameter("id"));
        try {
            Toy toy = this.toyService.getById(id);
            try(Writer writer = response.getWriter()) {
                String form = this.wrapEditForm(toy);
                String page  = this.wrapPage(form);
                writer.write(page);
            }
        } catch (SQLException | IOException e) {
            throw new ServletException(e);
        }
    }



    private void save(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, SQLException {
        if (!JakartaServletFileUpload.isMultipartContent(request)) {
            // 如果不是则停止
            Writer writer = response.getWriter();
            writer.write("Error: 表单必须包含 enctype=multipart/form-data");
            writer.flush();
            return;
        }

        // 配置上传参数
        DiskFileItemFactory factory = DiskFileItemFactory
                .builder()
                .setBufferSize(MEMORY_THRESHOLD)
                .get();

        JakartaServletFileUpload upload = new JakartaServletFileUpload(factory);
        // 设置最大文件上传值
        upload.setFileSizeMax(MAX_FILE_SIZE);
        // 设置最大请求值 (包含文件和表单数据)
        upload.setSizeMax(MAX_REQUEST_SIZE);
        // 中文处理
        upload.setHeaderCharset(Charset.forName("UTF-8"));
        // 构造临时路径来存储上传的文件
        // 这个路径相对当前应用的目录
        String uploadPath = request.getServletContext().getRealPath("./")
                + File.separator + UPLOAD_DIRECTORY;

        // 如果目录不存在则创建
        File uploadDir = new File(uploadPath);
        if (!uploadDir.exists()) {
            uploadDir.mkdir();
        }

        try {
            Toy toy = new Toy();
            Charset uft8 = Charset.forName("UTF-8");
            String imageName = UUID.randomUUID().toString();
            // 解析请求的内容提取文件数据
            @SuppressWarnings("unchecked")
            List<FileItem> formItems = upload.parseRequest(request);
            if (formItems != null && formItems.size() > 0) {
                // 迭代表单数据
                for (FileItem item : formItems) {
                    // 处理不在表单中的字段
                    if (!item.isFormField()) {
                        String image = new File(item.getName()).getName();
                        imageName += image.substring(image.lastIndexOf("."));
                        String filePath = uploadPath + File.separator + imageName;
                        File storeFile = new File(filePath);
                        // 在控制台输出文件的上传路径
                        System.out.println(filePath);
                        // 保存文件到硬盘
                        item.write(storeFile.toPath());
                        toy.setImage(imageName);
                    } else {
                        if (item.getFieldName().equals("id")) {
                            toy.setId(Integer.parseInt(item.getString()));
                        } else if (item.getFieldName().equals("name")) {
                            toy.setName(item.getString(uft8));
                        } else if (item.getFieldName().equals("brand")) {
                            toy.setBrand(item.getString(uft8));
                        } else if (item.getFieldName().equals("price")) {
                            toy.setPrice(Double.valueOf(item.getString(uft8)));
                        } else if (item.getFieldName().equals("memo")) {
                            toy.setMemo(item.getString(uft8));
                        } else if (item.getFieldName().equals("produce")) {
                            try {
                                toy.setProduce(ToyService.simpleDateFormat.parse(item.getString(uft8)));
                            } catch (ParseException e) {
                                throw new RuntimeException(e);
                            }
                        }
                    }
                }
            }

            this.toyService.save(toy);
            response.sendRedirect("./list");
        } catch (IOException ex) {
            throw new ServletException(ex);
        }
    }

    private void search(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, SQLException {
        String key = request.getParameter("key");
        try {
            List<Toy> toys = this.toyService.search(key);
            try(Writer writer = response.getWriter()) {
                String table = this.wrapTable(toys);
                String page  = this.wrapPage(table);
                writer.write(page);
            }
        } catch (SQLException | IOException e) {
            throw new ServletException(e);
        }
    }

    private String wrapTable(List<Toy> toys) {
        StringBuilder sb = new StringBuilder();
        sb.append("<table class='bs'>\n");
        sb.append("<tr><th>编号</th><th>玩具名</th><th>品牌</th><th>价格</th><th>描述</th><th>制造日期</th><th>图片</th><th></th><th></th></tr>\n");
        for (Toy toy : toys) {
            sb.append("<tr>");
            sb.append("<td class='centr'>").append(toy.getId()).append("</td>");
            sb.append("<td>").append(toy.getName()).append("</td>");
            sb.append("<td>").append(toy.getBrand()).append("</td>");
            sb.append("<td class='centr'>").append(toy.getPrice()).append("</td>");
            sb.append("<td>").append(toy.getMemo()).append("</td>");
            sb.append("<td class='centr'>").append(toy.getProduce()).append("</td>");
            sb.append("<td class='centr'><img class='toy-img-thumbnail' src='../upload/").append(toy.getImage()).append("'/></td>");
            sb.append("<td class='centr'><a href='./delete?id=" + toy.getId() + "'>删除</a></td>");
            sb.append("<td class='centr'><a href='./edit?id=" + toy.getId() + "'>修改</a></td>");
            sb.append("</tr>");
        }
        sb.append("</table>");
        return sb.toString();
    }

    private String wrapEditForm(Toy toy) {
        StringBuilder sb = new StringBuilder();
        sb.append("<center><br>")
            .append("<form action=\"./update\" method=\"post\" enctype=\"multipart/form-data\">")
            .append("<input type=\"hidden\" name=\"id\" value=\"" + toy.getId() + "\"><br><br>")
            .append("玩具名：<input type=\"text\" name=\"name\" value=\"" + toy.getName() + "\"><br><br>")
            .append("品牌：<input type=\"text\" name=\"brand\" value=\"" + toy.getBrand() + "\"><br><br>")
            .append("价格：<input type=\"text\" name=\"price\" value=\"" + toy.getPrice() +"\"><br><br>")
            .append("备注：<input type=\"text\" name=\"memo\" value=\"" + toy.getMemo() +"\"><br><br>")
            .append("日期：<input type=\"text\" name=\"produce\" value=\"" + toy.getProduce() + "\"><br><br>")
            .append("图片：<input type=\"file\" name=\"image\"><br><br>")
            .append("<input type=\"submit\" name=\"submit\" value=\"更新玩具\"/>")
            .append("</form>")
            .append("</center>");
        return sb.toString();
    }



}
